﻿// A Force-Directed Diagram Layout Algorithm
// Bradley Smith - 2010/07/01

using System;
using System.Collections.Generic;
using System.Windows;
using Windows.UI.Xaml.Shapes;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.Foundation;
using FriendAnalyzer.UIHelpers;
/// <summary>
/// Represents a node that can be added to a diagram and connected to other nodes. 
/// Provides logic for drawing itself and its connections to other nodes.
/// </summary>
/// 
namespace FriendAnalyzer.Graph
{
    public abstract class Node
    {
        public Rectangle maximumBounds;
        public string Name;
        public string imageID;
        Diagram mDiagram;			// the parent diagram
        Point mLocation;			// node position, relative to the origin
        	// list of references to connected nodes (children)
        public Node Parent;
        /// <summary>
        /// Gets or sets the position of the node.
        /// </summary>
        public Point Location
        {
            get { return mLocation; }
            set { mLocation = value; }
        }
        /// <summary>
        /// Gets a read-only collection representing the (child) nodes that this node is connected to.
        /// </summary>
        public List<Node> Connections;
        /// <summary>
        /// Gets or sets the diagram to which this node belongs.
        /// </summary>
        public Diagram Diagram
        {
            get { return mDiagram; }
            set
            {
                if (mDiagram == value) return;

                if (mDiagram != null) mDiagram.RemoveNode(this);
                mDiagram = value;
                if (mDiagram != null) mDiagram.AddNode(this);
            }
        }
        /// <summary>
        /// Gets or sets the X coordinate of the node, relative to the origin.
        /// </summary>
        public double X
        {
            get { return mLocation.X; }
            set { mLocation.X = value; }
        }
        /// <summary>
        /// Gets or sets the Y coordinate of the node, relative to the origin.
        /// </summary>
        public double Y
        {
            get { return mLocation.Y; }
            set { mLocation.Y = value; }
        }
        /// <summary>
        /// Gets the size of the node (for drawing purposes).
        /// </summary>
        //public abstract Size Size
        //{
        //    get;
        //}

        /// <summary>
        /// Initialises a new instance of the Node class.
        /// </summary>
        public Node()
        {
            mLocation = Point.Empty;
            mDiagram = null;
            Connections = new List<Node>();
        }

        /// <summary>
        /// Connects the specified child node to this node.
        /// </summary>
        /// <param name="child">The child node to add.</param>
        /// <returns>True if the node was connected to this node.</returns>
        public bool AddChild(Node child)
        {
            if (child == null) throw new ArgumentNullException("child");
            if ((child != this) && !this.Connections.Contains(child))
            {
                child.Diagram = this.Diagram;
                this.Connections.Add(child);
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Connects this node to the specified parent node.
        /// </summary>
        /// <param name="parent">The node to connect to this node.</param>
        /// <returns>True if the other node was connected to this node.</returns>
        public bool AddParent(Node parent)
        {
            if (parent == null) throw new ArgumentNullException("parent");
            return parent.AddChild(this);
        }

        /// <summary>
        /// Removes any connection between this node and the specified node.
        /// </summary>
        /// <param name="other">The other node whose connection is to be removed.</param>
        /// <returns>True if a connection existed.</returns>
        public bool Disconnect(Node other)
        {
            bool c = this.Connections.Remove(other);
            bool p = other.Connections.Remove(this);
            return c || p;
        }

        /// <summary>
        /// Draws a connector between this node and the specified child node using GDI+. 
        /// The source and destination coordinates (relative to the Graphics surface) are also specified.
        /// </summary>
        /// <param name="graphics">GDI+ Graphics surface.</param>
        /// <param name="from">Source coodinate.</param>
        /// <param name="to">Destination coordinate.</param>
        /// <param name="other">The other node.</param>
        public virtual void DrawConnector(Canvas graphics, Point from, Point to, Node other)
        {
            //Line line = new Line();
            //line.Fill = new SolidColorBrush { Color = Colors.Red };
            //line.StrokeThickness = 2;
            //line.Stroke = new SolidColorBrush { Color = Colors.Gray };
            //line.X1 = from.X;
            //line.X2 = to.X;
            //line.Y1 = from.Y;
            //line.Y2 = to.Y;
            //graphics.Children.Add(line);
        }
        /// <summary>

        public abstract RadGrid DrawNode(Canvas graphics, Rectangle bounds, bool big, BitmapImage bmp, SolidColorBrush brush);
    }

    /// <summary>
    /// Provides an example implementation of the Node class. SpotNode is an 8x8 circle that is stroked and filled.
    /// </summary>
    public class SpotNode : Node
    {
        private SolidColorBrush mFill;

        /// <summary>
        /// Gets or sets the System.Drawing.Brush used to fill the spot.
        /// </summary>
        public SolidColorBrush Fill
        {
            get { return mFill; }
            set
            {
                if (value == null) throw new ArgumentNullException("value");
                mFill = value;
            }
        }
        /// <summary>
        /// Gets the size of the spot.
        /// </summary>
        //public override Size Size
        //{
        //    get
        //    {
        //        return new Size(8, 8);
        //    }
        //}
        /// <summary>
        /// Gets or sets the System.Drawing.Pen used to stroke the spot.
        /// </summary>



        /// <summary>
        /// Initalises a new instance of the SpotNode class using the specified fill color.
        /// </summary>
        /// <param name="color">The System.Drawing.Color to fill the spot with.</param>
        public SpotNode(Color color, string Name,string imageID)
            : base()
        {
            mFill = new SolidColorBrush(color);
            this.Name = Name;
            this.imageID = imageID;
        }
        /// <summary>
        /// Draws the node using GDI+.
        /// </summary>
        /// <param name="graphics">GDI+ Graphics surface.</param>
        /// <param name="bounds">The bounds in which to draw the node.</param>
        public override RadGrid DrawNode(Canvas graphics, Rectangle bounds, bool big,BitmapImage bmp,SolidColorBrush brush)
        {
           
            int discriminator = 0;
            if (big)
            {
                discriminator = 40;
            }
            else
            {
                discriminator = 25;
            }
            //aici bagat si imaginea in grid
            RadGrid grid = new RadGrid();
            TextBlock tt = new TextBlock();
            tt.Text = this.Name; tt.Margin = new Windows.UI.Xaml.Thickness(0, 3, 0, 3);

                Windows.UI.Xaml.Shapes.Rectangle r = new Windows.UI.Xaml.Shapes.Rectangle();
                r.Fill = brush;
                r.Width = discriminator * 2;
                r.Height = discriminator * 2;
                r.Stroke = new SolidColorBrush(Colors.Black);
                r.StrokeThickness = 2;
                grid.Children.Add(r);

                Grid grdSmall = new Grid();
                grdSmall.Margin = new Windows.UI.Xaml.Thickness(0, 5, 0, 0);
                grdSmall.Width = discriminator * 2 - 20;
                grdSmall.Height = discriminator * 2 - 20;

                grid.Children.Add(grdSmall);

                Image img = new Image();
                img.Source = bmp;
                img.Stretch = Stretch.Fill;
                grdSmall.Children.Add(img);
          
            grid.Children.Add(tt);
            graphics.Children.Add(grid);
            Canvas.SetLeft(grid, bounds.X-discriminator );
            Canvas.SetTop(grid, bounds.Y - discriminator);
            return grid;
        }

    }

}